const { ccclass, property } = cc._decorator;

@ccclass
export default class CocosHelperUtil {
    static GotoScene(sceneName: string, callback?: Function) {
        let loaded = false;
        if (sceneName && this.GetCurSceneName() != sceneName) {
            cc.log("go to scene: " + sceneName);
            loaded = cc.director.loadScene(sceneName, callback);
        }
        return loaded;
    };

    static PreloadScene(sceneName: string, callback?: Function) {
        if (sceneName) {
            cc.director.preloadScene(sceneName, function (error) {
                if (callback) {
                    callback(error);
                }
            });
        }
    };

    static GetCurSceneName() {
        return cc.director.getScene().name;
    };

    static SetEnable(component: cc.Component, enabled: boolean) {
        if (component) {
            enabled = !!enabled;
            if (component.enabled !== enabled) {
                component.enabled = enabled;
            }
        }
    };

    static SetActive(node: cc.Node, active: boolean) {
        if (node) {
            active = !!active;
            if (node instanceof cc.Component && node.isValid && node.node.active !== active) {
                node.node.active = active;
            } else if (node.isValid && node.active !== active) {
                node.active = active;
            }
        }
    };

    static SetVisible(sprite: cc.Sprite | cc.Label, visible: boolean) {
        if (sprite) {
            sprite.node ? sprite.node.opacity = visible ? 255 : 0 : sprite.opacity && (sprite.opacity = visible ? 255 : 0);
        }
    };

    static SetOpaque(sprite: cc.Sprite | cc.Label, opaque: number) {
        if (sprite) {
            sprite.node ? sprite.node.opacity = opaque : sprite.opacity && (sprite.opacity = opaque);
        }
    };

    static Instantiate(prefab: cc.Prefab, parent: cc.Node, component?: { new(): cc.Component }): cc.Component | null {
        let instance: cc.Component | null = null;
        if (prefab) {
            let node = cc.instantiate(prefab);
            if (node) {
                instance = component ? node.getComponent(component) || node.addComponent(component) : node;
                parent && (parent.node ? parent.node.addChild(node) : parent.addChild(node));
            }
        }
        return instance;
    };

    static SetPos(node: cc.Node | cc.Component, x: number, y: number) {
        if (node) {
            if (node instanceof cc.Component) {
                node.node.setPosition(x, y);
            } else {
                node.setPosition(x, y);
            }
        }
    };

    static GetPos(node: cc.Node | cc.Component, defaultPos: cc.Vec2 = cc.v2(0, 0)): cc.Vec2 {
        if (node) {
            defaultPos = node.node ? node.node.getPosition() : node.getPosition();
        }
        return defaultPos;
    };

    static GetRotation(node: cc.Node | cc.Component, defaultRotation: cc.Vec2 = cc.v2(0, 0)): cc.Vec2 {
        if (node) {
            defaultRotation = node.node ? node.node.getRotation() : node.getRotation();
        }
        return defaultRotation;
    };

    static SetRotation(node: cc.Node | cc.Component, rotation: number, angle?: number) {
        if (node) {
            if (node instanceof cc.Component) {
                node.node.setRotation(rotation, angle);
            } else {
                node.setRotation(rotation, angle);
            }
        }
    };

    static SetSize(node: cc.Node | cc.Component, width: number, height: number) {
        if (node && width !== undefined && height !== undefined) {
            if (node instanceof cc.Component) {
                node.node.setContentSize(width, height);
            } else {
                node.setContentSize(width, height);
            }
        }
    };

    static SetScale(node: cc.Node | cc.Component, scale: number) {
        if (node) {
            if (node instanceof cc.Component) {
                node.node.setScale(scale);
            } else {
                node.setScale(scale);
            }
        }
    };

    static SetScaleX(node: cc.Node | cc.Component, scaleX: number) {
        if (node) {
            if (node instanceof cc.Component) {
                node.node.setScaleX(scaleX);
            } else {
                node.setScaleX(scaleX);
            }
        }
    };

    static SetScaleY(node: cc.Node | cc.Component, scaleY: number) {
        if (node) {
            if (node instanceof cc.Component) {
                node.node.setScaleY(scaleY);
            } else {
                node.setScaleY(scaleY);
            }
        }
    };

    static SetText(label: cc.Label, text: any) {
        if (label && text !== null) {
            text = "" + text;
            label.string = text;
        }
    };

    static SetColor(node: cc.Node | cc.Component, color: cc.Color) {
        if (node && color && node.color) {
            node.color = color;
        }
    };

    static SetPageViewEnable(pageView: cc.PageView, enabled: boolean) {
        if (pageView) {
            if (enabled) {
                pageView.node.on(cc.Node.EventType.TOUCH_MOVE, pageView._onTouchMoved, pageView.node, true);
            } else {
                pageView.node.off(cc.Node.EventType.TOUCH_MOVE, pageView._onTouchMoved, pageView.node, true);
            }
        }
    };

    static ChangeSpriteFrame(sprite: cc.Sprite, spriteFrame: cc.SpriteFrame) {
        if (sprite instanceof cc.Sprite && spriteFrame instanceof cc.SpriteFrame) {
            sprite.spriteFrame = spriteFrame;
        }
    };

    static GetSpriteFrameName(sprite: cc.Sprite): string {
        let frameName = "";
        if (sprite && sprite instanceof cc.Sprite && sprite.spriteFrame) {
            frameName = sprite.spriteFrame.name;
        }
        return frameName;
    };

    static GetLabelString(label: cc.Label): string {
        let labelString = "";
        if (label && label instanceof cc.Label) {
            labelString = label.string;
        }
        return labelString;
    };

    static StopAllActions(node: cc.Node | cc.Component) {
        if (node) {
            let targetNode = node.node ? node.node : node;
            if (targetNode) {
                targetNode.stopAllActions();
            }
        }
    };

    static MoveTo(target: cc.Node | cc.Component, position: cc.Vec2, duration: number, easing?: number, callback?: Function) {
        if (target) {
            let node = target.node ? target.node : target;
            if (node) {
                if (position) {
                    this.SetPos(node, position.x, position.y);
                }
                let action = cc.moveTo(duration, position);
                if (callback) {
                    node.runAction(cc.sequence(action, cc.callFunc(() => {
                        callback();
                    }, this)));
                } else {
                    node.runAction(action);
                }
            }
        }
    };

    static ScaleTo(target: cc.Node | cc.Component, scale: number, duration: number, callback?: Function) {
        if (target) {
            let node = target.node ? target.node : target;
            if (node) {
                let action = cc.scaleTo(duration, scale);
                if (callback) {
                    node.runAction(cc.sequence(action, cc.callFunc(() => {
                        callback();
                    }, this)));
                } else {
                    node.runAction(action);
                }
            }
        }
    };

    static GetComponent(node: cc.Node | cc.Component, type: { new(): cc.Component }): cc.Component | null {
        let component = null;
        let targetNode = node.node ? node.node : node;
        if (targetNode) {
            component = targetNode.getComponent(type) || targetNode.getComponentInChildren(type);
        }
        return component;
    };

    static GetComponentsInChildren(node: cc.Node | cc.Component, type: { new(): cc.Component }, includeInactive?: boolean, includeNested?: boolean): cc.Component[] {
        let components: cc.Component[] = [];
        let targetNode = node.node ? node.node : node;
        if (targetNode) {
            if (includeInactive) {
                if (includeNested) {
                    components = targetNode.getComponentsInChildren(type);
                } else {
                    let component = targetNode.getComponent(type);
                    if (component) {
                        components.push(component);
                    }
                    let children = targetNode.children;
                    let childCount = targetNode.childrenCount;
                    for (let i = 0; i < childCount; i++) {
                        let childComponent = children[i].getComponent(type);
                        if (childComponent) {
                            components.push(childComponent);
                        }
                    }
                }
            } else {
                if (includeNested) {
                    components = targetNode.getComponents(type);
                } else {
                    let component = targetNode.getComponent(type);
                    if (component) {
                        components.push(component);
                    }
                }
            }
        }
        return components;
    };

    static PlayAnimation(node: cc.Node | cc.Component, animationName: string, callback?: Function) {
        if (node) {
            let targetNode = node.node ? node.node : node;
            let animation = targetNode.getComponent(cc.Animation);
            if (animation && animation.getAnimationState(animationName)) {
                let animState = animation.play(animationName);
                if (callback) {
                    animState.on('finished', () => {
                        callback();
                    }, this);
                }
            }
        }
    };

    static StopAnimation(node: cc.Node | cc.Component) {
        if (node) {
            let targetNode = node.node ? node.node : node;
            let animation = targetNode.getComponent(cc.Animation);
            if (animation) {
                animation.stop();
            }
        }
    };

    static PauseAnimation(node: cc.Node | cc.Component) {
        if (node) {
            let targetNode = node.node ? node.node : node;
            let animation = targetNode.getComponent(cc.Animation);
            if (animation) {
                animation.pause();
            }
        }
    };

    static ResumeAnimation(node: cc.Node | cc.Component) {
        if (node) {
            let targetNode = node.node ? node.node : node;
            let animation = targetNode.getComponent(cc.Animation);
            if (animation) {
                animation.resume();
            }
        }
    };

    static CallFunc(target: any, func: Function) {
        if (target && target.isValid && typeof func === 'function') {
            let action = cc.callFunc(() => {
                func.call(target);
            });
            return action;
        }
        return null;
    };
}

